<script setup>
import { ref, onMounted, nextTick } from 'vue'
import { useRouter } from 'vue-router'
import dayjs from 'dayjs'
import { ElMessage, ElMessageBox } from 'element-plus'
import { myCommentsPage, updateComment, deleteCommentById } from '@/api/comment'
import { getMovie } from '@/api/movies'
import { VideoCamera } from '@element-plus/icons-vue'

const router = useRouter()

const list = ref([])
const loading = ref(false)
const pageNo = ref(1)
const pageSize = ref(10)
const total = ref(0)

const editVisible = ref(false)
const editForm = ref({ id: null, mname: '', score: 8.0, content: '' })
const editSubmitting = ref(false)

// 电影详情缓存与海报展示
const movieMap = ref({})
const cleanUrl = (url) => (url ? String(url).replace(/`/g, '').trim() : '')
const posterSrc = (movie) => cleanUrl(movie?.posterUrl) || cleanUrl(movie?.imageUrl) || cleanUrl(movie?.poster) || cleanUrl(movie?.cover) || ''
const goMovie = (mid) => router.push(`/movie/${mid}`)
const enrichMovies = async (records) => {
  const mids = [...new Set(records.map(r => r.mid).filter(Boolean))]
  await Promise.all(mids.map(async mid => {
    if (movieMap.value[mid]) return
    try {
      const res = await getMovie(mid)
      if (res?.code === '200') movieMap.value[mid] = res.data || {}
    } catch (e) {}
  }))
}

// 富文本编辑器（禁止图片/视频）
const editEditor = ref(null)
const format = (cmd) => document.execCommand(cmd, false)
const formatBlock = (block) => document.execCommand('formatBlock', false, block)
const insertList = (cmd) => document.execCommand(cmd, false)
const createLink = () => {
  const url = window.prompt('输入链接地址（http/https）：', 'https://')
  if (!url) return
  if (!/^https?:\/\//i.test(url)) { ElMessage.error('仅允许 http/https 链接'); return }
  document.execCommand('createLink', false, url)
}
const clearFormats = () => {
  if (editEditor.value) {
    const text = editEditor.value.innerText || ''
    const lines = text.split('\n').map(l => `<p>${l.replace(/\s+/g,' ').trim()}</p>`).join('')
    editForm.value.content = lines
    editEditor.value.innerHTML = editForm.value.content
  }
}
const onPastePlain = (e) => {
  const text = (e.clipboardData || window.clipboardData).getData('text/plain')
  document.execCommand('insertText', false, text)
}
const onDropPrevent = () => {}

// 处理中文输入法组合，避免 caret 跳动
const composingEdit = ref(false)
const onEditInput = (e) => { if (composingEdit.value) return; editForm.value.content = e.target.innerHTML }
const onEditCompStart = () => { composingEdit.value = true }
const onEditCompEnd = (e) => { composingEdit.value = false; editForm.value.content = e.target.innerHTML }
 
 const sanitizeHtml = (html) => {
  if (!html) return ''
  const parser = new DOMParser()
  const doc = parser.parseFromString(String(html), 'text/html')
  const allowed = new Set(['p','br','b','i','u','strong','em','span','a','ul','ol','li','blockquote','code','pre','h1','h2','h3','h4'])
  const walk = (node) => {
    const children = Array.from(node.childNodes)
    for (const child of children) {
      if (child.nodeType === 1) {
        const tag = child.tagName.toLowerCase()
        if (!allowed.has(tag)) {
          while (child.firstChild) node.insertBefore(child.firstChild, child)
          node.removeChild(child)
          continue
        }
        const attrs = Array.from(child.attributes || [])
        for (const attr of attrs) {
          const name = attr.name.toLowerCase()
          const isEvent = name.startsWith('on')
          const isDanger = ['style','src','data','xlink:href'].includes(name)
          if (isEvent || isDanger || (child.tagName.toLowerCase() !== 'a' && name !== 'href')) {
            child.removeAttribute(name)
          }
        }
        if (tag === 'a') {
          let href = child.getAttribute('href') || ''
          if (!/^https?:\/\//i.test(href)) child.removeAttribute('href')
        }
        walk(child)
      }
    }
  }
  walk(doc.body)
  return doc.body.innerHTML
}

const loadMyComments = async () => {
  loading.value = true
  try {
    const res = await myCommentsPage({ pageNo: pageNo.value, pageSize: pageSize.value })
    if (res.code === '200') {
      list.value = res.data?.records || []
      total.value = res.data?.total || 0
      await enrichMovies(list.value)
    } else {
      ElMessage.error(res.msg || '加载失败')
    }
  } catch (e) {} finally {
    loading.value = false
  }
}

const openEdit = (row) => {
  editForm.value = {
    id: row.id,
    mname: row.mname || '',
    score: Number(row.score || 8.0),
    content: row.content || '',
  }
  editVisible.value = true
  nextTick(() => { if (editEditor.value) editEditor.value.innerHTML = editForm.value.content || '' })
}

const submitEdit = async () => {
  if (!editForm.value.id) return
  const plain = String(editForm.value.content || '').replace(/<[^>]+>/g, '').trim()
  if (!plain) { ElMessage.error('评论内容不能为空'); return }
  editSubmitting.value = true
  try {
    const res = await updateComment({ id: editForm.value.id, score: Number(editForm.value.score), content: sanitizeHtml(editForm.value.content) })
    if (res.code === '200') {
      ElMessage.success(res.msg || '更新成功')
      editVisible.value = false
      await loadMyComments()
    } else {
      ElMessage.error(res.msg || '更新失败')
    }
  } catch (e) {} finally {
    editSubmitting.value = false
  }
}

const confirmDelete = async (row) => {
  try {
    await ElMessageBox.confirm('确认删除该评论？', '提示', { type: 'warning' })
    const res = await deleteCommentById(row.id)
    if (res.code === '200') {
      ElMessage.success(res.msg || '删除成功')
      await loadMyComments()
    } else {
      ElMessage.error(res.msg || '删除失败')
    }
  } catch (e) {
    // 取消或错误
  }
}

onMounted(() => {
  const token = localStorage.getItem('token')
  if (!token) { ElMessage.info('请先登录'); router.push('/login'); return }
  loadMyComments()
})

const goHome = () => router.push('/')
</script>

<template>
  <div class="page">
    <div class="topbar">
      <div class="brand">
        <el-icon><VideoCamera /></el-icon>
        <span>我的评论</span>
      </div>
      <div class="actions">
        <el-link type="primary" @click="goHome">返回首页</el-link>
      </div>
    </div>

    <section class="content" v-loading="loading">
      <div v-if="list.length" class="grid">
        <el-card v-for="c in list" :key="c.id" class="card" shadow="hover">
          <div class="card-header">
            <div class="name">{{ c.mname || '未命名影片' }}</div>
            <el-tag type="info">评分 {{ c.score }}</el-tag>
          </div>
          <div class="card-body">
            <div class="poster-sm" v-if="posterSrc(movieMap[c.mid])">
              <img :src="posterSrc(movieMap[c.mid])" :alt="c.mname || 'poster'" />
            </div>
            <div class="info">
              <div class="meta-row">
                <span class="time">{{ dayjs(c.cotime || c.createdAt).format('YYYY-MM-DD HH:mm') }}</span>
                <el-button text type="primary" @click.stop="goMovie(c.mid)">前往电影</el-button>
              </div>
              <div class="content" v-html="sanitizeHtml(c.content)" />
            </div>
          </div>
          <div class="card-footer">
            <el-button size="small" type="primary" text @click.stop="openEdit(c)">编辑</el-button>
            <el-button size="small" type="danger" text @click.stop="confirmDelete(c)">删除</el-button>
          </div>
        </el-card>
      </div>
      <el-empty v-else description="暂无评论" />
      <div class="pager" v-if="total > 0">
        <el-pagination
          background
          layout="prev, pager, next"
          :total="total"
          :page-size="pageSize"
          :current-page="pageNo"
          @current-change="(p)=>{ pageNo = p; loadMyComments() }"
        />
      </div>
    </section>

    <!-- 编辑弹窗 -->
    <el-dialog v-model="editVisible" title="编辑评论" width="640px" :close-on-click-modal="false">
      <div class="edit-dialog">
        <div class="row">
          <div class="label">影片</div>
          <div class="value"><span class="value-text">{{ editForm.mname }}</span></div>
        </div>
        <div class="row">
          <div class="label">评分</div>
          <div class="value"><el-input-number v-model="editForm.score" :min="0" :max="10" :step="0.5" controls-position="right" /></div>
        </div>
        <div class="row">
          <div class="label">内容</div>
          <div class="value">
            <div class="toolbar">
              <el-button size="small" @click="format('bold')">加粗</el-button>
              <el-button size="small" @click="format('italic')">斜体</el-button>
              <el-button size="small" @click="format('underline')">下划线</el-button>
              <el-button size="small" @click="formatBlock('blockquote')">引用</el-button>
              <el-button size="small" @click="formatBlock('p')">段落</el-button>
              <el-button size="small" @click="insertList('insertUnorderedList')">• 列表</el-button>
              <el-button size="small" @click="insertList('insertOrderedList')">1. 列表</el-button>
              <el-button size="small" @click="createLink()">链接</el-button>
              <el-button size="small" @click="clearFormats()">清除样式</el-button>
            </div>
            <div
               ref="editEditor"
               class="editor"
               contenteditable="true"
               @input="onEditInput"
               @compositionstart="onEditCompStart"
               @compositionend="onEditCompEnd"
               @paste.prevent="onPastePlain"
               @drop.prevent="onDropPrevent"
             ></div>
          </div>
        </div>
      </div>
      <template #footer>
        <div class="dialog-footer">
          <el-button @click="editVisible = false">取消</el-button>
          <el-button type="primary" :loading="editSubmitting" @click="submitEdit">保存</el-button>
        </div>
      </template>
    </el-dialog>
  </div>
</template>

<style scoped>
.page { min-height: 100vh; background: radial-gradient(1000px 500px at 10% 10%, rgba(99,102,241,0.15), transparent), radial-gradient(800px 400px at 90% 0%, rgba(16,185,129,0.12), transparent), #0b1020; color: #e5e7eb; padding: 16px 24px; }
.topbar { display: flex; align-items: center; justify-content: space-between; padding: 16px 24px; }
.brand { display: flex; align-items: center; gap: 8px; font-size: 18px; font-weight: 600; }
.content { padding: 0 12px 24px; }
.grid { display: grid; grid-template-columns: 1fr; gap: 12px; }
.card { background: rgba(255,255,255,0.12); border-radius: 14px; border: 1px solid rgba(255,255,255,0.22); box-shadow: 0 6px 18px rgba(0,0,0,0.35); }
.card :deep(.el-card__body) { padding: 12px; }
.card-header { display: flex; align-items: center; justify-content: space-between; }
.name { font-weight: 600; color: #f1f5f9; }
.card-body { display: grid; grid-template-columns: 160px 1fr; gap: 12px; color: #e5e7eb; }
.poster-sm img { width: 100%; height: 160px; object-fit: cover; border-radius: 8px; display: block; }
.meta-row { display: flex; gap: 12px; align-items: center; margin-bottom: 6px; color: #dbeafe; }
.meta-row .time { color: #cbd5e1; }
.content { color: #e2e8f0; }
.card-footer { display: flex; justify-content: flex-end; gap: 8px; padding-top: 6px; }
.pager { display: flex; justify-content: center; margin-top: 12px; }

/* 编辑弹窗布局优化 */
.edit-dialog { padding: 6px 2px; color: #1f2b38; }
.row { display: grid; grid-template-columns: 80px 1fr; gap: 10px; align-items: center; padding: 8px 0; }
.label { color: #606266; }
.value-text { font-weight: 600; }
.value :deep(.el-input-number) { width: 160px; }

/* 富文本编辑器样式 */
.toolbar { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 6px; }
.editor { min-height: 180px; border: 1px solid #dcdfe6; border-radius: 4px; padding: 8px; background: #fff; overflow: auto; white-space: pre-wrap; }
.editor:empty:before { content: '编辑你的评论…'; color: #c0c4cc; }
.editor p { margin: 0 0 8px; }
.editor ul, .editor ol { padding-left: 20px; margin: 0 0 8px; list-style-position: outside; }
.editor blockquote { margin: 0 0 8px; padding-left: 10px; border-left: 3px solid #ebeef5; color: #606266; }
</style>